import G6 from '@antv/g6'
import { hexToRgba } from '@/utils/color.js'
import { ext } from '@antv/matrix-util'
const transform = ext.transform

export default function StationNode() {
  G6.registerNode(
    'stationNode',
    {
      update(cfg, item) {
        const group = item.getContainer()
        const children = group.get('children')
        const mainBox = children.find((item) => item.get('name') === 'main-box' || item.get('name') === 'rect-main-box')
        const nodeLabel = children.find((item) => item.get('name') === 'node-label')

        // 更新文本属性
        if (cfg.textAttrs && nodeLabel) {
          nodeLabel.attr(cfg.textAttrs)
        }

        // 更新其他属性
        if (cfg.style && mainBox) {
          mainBox.attr(cfg.style)
        }
      },
      setState(name, value, item) {
        const model = item.getModel()
        const group = item?.getContainer()
        const children = group?.get('children')
        const mainBox = children.find((item) => item.get('name') === 'main-box')
        const nodeLabel = children.find((item) => item.get('name') === 'node-label')
        const nodeHighlight = children.find((item) => item.get('name') === 'node-highlight')
        switch (name) {
          case 'dark':
            mainBox?.attr('opacity', value ? 0.2 : 1)
            nodeLabel?.attr('opacity', value ? 0.2 : 1)
            break
          case 'highlight':
            nodeHighlight?.attr('opacity', value ? 1 : 0)
            value ? item?.toFront() : item?.toBack()
            break
        }
      },
      draw(cfg, group) {
        let shape = null
        if (cfg.shapeType === 'rect') {
          // 主体
          shape = group.addShape('rect', {
            attrs: {
              x: 0,
              y: 0,
              width: cfg.nodeSize[0],
              height: cfg.nodeSize[1],
              fill: '#fff',
              stroke: cfg.lineColor,
              lineWidth: 2,
              radius: 3,
              ...(cfg.style ?? {}),
            },
            name: 'rect-main-box',
            draggable: false,
            zIndex: 2,
          })

          // 高亮
          group.addShape('rect', {
            attrs: {
              x: 0 - 4,
              y: 0 - 4,
              width: cfg.nodeSize[0] + 8,
              height: cfg.nodeSize[1] + 8,
              cursor: 'pointer',
              fill: hexToRgba(cfg.lineColor, 0.25),
              stroke: hexToRgba(cfg.lineColor, 0.25),
              lineWidth: 4,
              opacity: 0,
              radius: 4,
            },
            name: 'node-highlight',
            draggable: false,
            zIndex: 1,
          })
        } else {
          shape = group.addShape('circle', {
            attrs: {
              x: 0,
              y: 0,
              r: cfg.nodeSize / 2,
              fill: '#fff',
              stroke: cfg.healthColor,
              lineWidth: 2,
              cursor: 'pointer',
            },
            name: 'main-box',
            draggable: false,
            zIndex: 3,
          })

          // 高亮
          group.addShape('circle', {
            attrs: {
              x: 0,
              y: 0,
              r: cfg.nodeSize / 2 + 8,
              cursor: 'pointer',
              fill: hexToRgba(cfg.healthColor, 0.25),
              opacity: 0,
            },
            name: 'node-highlight',
            draggable: false,
            zIndex: 1,
          })
        }

        // 计算标签旋转角度
        let labelRotate = 0
        const graph = group.get('graph')
        if (graph && cfg.id) {
          const node = graph.findById(cfg.id)
          if (node) {
            const model = node.getModel()
            // 获取前后节点
            const prevNode = model.prevId ? graph.findById(model.prevId) : null
            const nextNode = model.nextId ? graph.findById(model.nextId) : null

            if (prevNode && nextNode) {
              // 如果有前后节点，计算角平分线角度
              const prevModel = prevNode.getModel()
              const nextModel = nextNode.getModel()
              const dx1 = prevModel.x - model.x
              const dy1 = prevModel.y - model.y
              const dx2 = nextModel.x - model.x
              const dy2 = nextModel.y - model.y
              // 计算两个向量的角度
              const angle1 = Math.atan2(dy1, dx1)
              const angle2 = Math.atan2(dy2, dx2)
              // 计算角平分线角度（转换为度数）
              labelRotate = ((angle1 + angle2) / 2) * (180 / Math.PI)
            } else if (prevNode) {
              // 如果只有前节点
              const prevModel = prevNode.getModel()
              const dx = prevModel.x - model.x
              const dy = prevModel.y - model.y
              labelRotate = Math.atan2(dy, dx) * (180 / Math.PI)
            } else if (nextNode) {
              // 如果只有后节点
              const nextModel = nextNode.getModel()
              const dx = nextModel.x - model.x
              const dy = nextModel.y - model.y
              labelRotate = Math.atan2(dy, dx) * (180 / Math.PI)
            }

            // 调整角度使文字保持在上方
            if (labelRotate > 90) labelRotate -= 180
            if (labelRotate < -90) labelRotate += 180
          }
        }
        console.log(labelRotate, 'labelRotate')
        // 添加文本标签
        group.addShape('text', {
          attrs: {
            textAlign: 'center',
            textBaseline: 'top',
            x: cfg.shapeType === 'rect' ? cfg.nodeSize[0] / 2 : 0,
            y: cfg.shapeType === 'rect' ? cfg.nodeSize[1] + 8 : cfg.nodeSize / 2 + 8,
            matrix: labelRotate
              ? transform(
                  [1, 0, 0, 0, 1, 0, 0, 0, 1],
                  [
                    // 1. 第一步：将文本移动到原点
                    // 通过负向平移，将文本的旋转中心点移动到坐标原点(0,0)
                    // 对于矩形节点，移动距离为节点宽度的一半和节点高度+8的位置
                    // 对于圆形节点，移动距离为0和节点大小的一半+8的位置
                    ['t', -(cfg.shapeType === 'rect' ? cfg.nodeSize[0] / 2 : 0), -(cfg.shapeType === 'rect' ? cfg.nodeSize[1] + 8 : cfg.nodeSize / 2 + 8)],

                    // 2. 第二步：在原点进行旋转
                    // 将角度值从度数转换为弧度(角度 * PI / 180)
                    // 使用矩阵的 r 命令进行旋转变换
                    ['r', (labelRotate * Math.PI) / 180],

                    // 3. 第三步：将文本移回原来的位置
                    // 通过正向平移，将文本移动回原来的位置
                    // 移动距离与第一步相同，但方向相反
                    ['t', cfg.shapeType === 'rect' ? cfg.nodeSize[0] / 2 : 0, cfg.shapeType === 'rect' ? cfg.nodeSize[1] + 8 : cfg.nodeSize / 2 + 8],
                  ]
                )
              : null,
            ...(cfg.textAttrs ?? {}),
          },
          name: 'node-label',
          zIndex: 4,
        })

        group.sort()
        return shape
      },
    },
    'single-node'
  )
}
